package com.timedomain.him.remake.utils;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;

import com.timedomain.him.remake.models.ChatMessage;
import com.timedomain.him.remake.receiver.ChatMessageReceiver;
import com.timedomain.him.remake.ui.MessageActivity;
import com.timedomain.him.remake.yggdrasil.TheWorldTree;
import com.timedomain.him.remake.yggdrasil.YieldChatMessage;
import com.timedomain.him.remake.yggdrasil.YieldSelection;

import java.util.HashMap;
import java.util.Objects;

public class ActiveChatManager {

    public static final String EXTRA_TYPE = "type";
    public static final String EXTRA_TIME = "time";

    public static final String BROADCAST_NEW_MESSAGE = "com.timedomain.him.remake.utils.ActiveChatManager.BROADCAST_NEW_MESSAGE";

    private static final int CODE_MESSAGE_ALARM = 148;

    public static void checkMessage(Context ctx){
        long lastNotificationTime = AppSettings.lastNotificationTime;
        if(lastNotificationTime == -1){
            lastNotificationTime = TimeUtils.getTimeStampIgnoreTimeZone();
            AppSettings.lastNotificationTime = lastNotificationTime;
            AppSettings.saveSettings(ctx);
        }
        long current = TimeUtils.getTimeStampIgnoreTimeZone();
        MessageTimeAndType messageTimeAndType = getNextMessageTime(lastNotificationTime);
        while(messageTimeAndType.time < current){
            processOneMessage(ctx,messageTimeAndType,false);
            messageTimeAndType = getNextMessageTime(messageTimeAndType.time+1L);
        }
        AlarmManager alarmManager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
        Intent messageIntent = new Intent(ctx, ChatMessageReceiver.class);
        messageIntent.putExtra(EXTRA_TYPE,messageTimeAndType.type);
        messageIntent.putExtra(EXTRA_TIME,messageTimeAndType.time);
        PendingIntent alarmIntent = PendingIntent.getBroadcast(ctx,CODE_MESSAGE_ALARM,messageIntent,PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager.AlarmClockInfo aci = new AlarmManager.AlarmClockInfo(TimeUtils.toSystemTimeStamp(messageTimeAndType.time),alarmIntent);
        alarmManager.setAlarmClock(aci,alarmIntent);
    }

    public static void processOnMessageReceive(Context ctx, Intent intent){
        int type = intent.getIntExtra(EXTRA_TYPE,0);
        long time = intent.getLongExtra(EXTRA_TIME,-1);
        if(time != -1){
            processOneMessage(ctx,new MessageTimeAndType(time,type),true);
        }
        checkMessage(ctx);
    }

    private static void processOneMessage(Context ctx,MessageTimeAndType type,boolean showNotification){
        AppSettings.lastNotificationTime = type.time +1;
        AppSettings.saveSettings(ctx);
        if(TimeUtils.getTimeStampIgnoreTimeZone() -  AppSettings.lastChatMessageTime < 30000){
            HLog.w("ActiveChatManager", "processOneMessage: a recent chat is taking place. ignore");
            return;
        }

        if(TimeUtils.getTimeStampIgnoreTimeZone() - AppSettings.lastChatMessageTime < 30 * 60 * 1000){
            if(!AppSettings.savedWorldState.equals(TheWorldTree.LEAF_ENTRY)){
                return;
            }
        }

        HashMap<Integer,String> typeStateMap = new HashMap<>();
        typeStateMap.put(MessageTimeAndType.TYPE_ASK,"[::Weekday1]");
        typeStateMap.put(MessageTimeAndType.TYPE_KNOWLEDGE,"[::Weekday2]");
        typeStateMap.put(MessageTimeAndType.TYPE_NIGHT,"[::Night]");

        if(type.type == MessageTimeAndType.TYPE_NIGHT){
            if(AppSettings.nightChatDay == TimeUtils.toDateStamp(TimeUtils.getTimeStampIgnoreTimeZone())){
                return;
            }

            MorningCallManager.setNextMorningCall(ctx);
        }

        TheWorldTree theWorldTree = new TheWorldTree(ctx);
        theWorldTree.loadState(Objects.requireNonNull(typeStateMap.get(type.type)));
        String message = "点击查看";
        try {
            theWorldTree.nextTick();
        } catch (YieldChatMessage yieldChatMessage) {
            ChatMessage cm = new ChatMessage(type.time,"",ChatMessage.TYPE_TIME,"","");
            DB.ChatMessage.Add(cm);
            yieldChatMessage.message.date = type.time+1;
            DB.ChatMessage.Add(yieldChatMessage.message);
            message = "「他」: "+yieldChatMessage.message.content;
        } catch (YieldSelection yieldSelection) {
            // Do nothing
        }
        AppSettings.savedWorldState = theWorldTree.saveState();
        AppSettings.lastChatMessageTime = type.time;
        AppSettings.saveSettings(ctx);
        if(showNotification){
            NotificationUtils.postNoificationAllowRemoval(ctx,"「他」(1条新消息)",message, MessageActivity.class);
        }
        ctx.sendBroadcast(new Intent(BROADCAST_NEW_MESSAGE));
    }

    private static MessageTimeAndType getNextMessageTime(){
        return getNextMessageTime(TimeUtils.getTimeStampIgnoreTimeZone());
    }

    private static MessageTimeAndType getNextMessageTime(long currentTime){
        long beginOfToday =TimeUtils.dateStampToTimeStamp(TimeUtils.toDateStamp(currentTime));
        while (true) {
            int dayOfWeek = TimeUtils.getDayOfWeek(beginOfToday);
            long tenOClock = beginOfToday + 6L * 3600L * 1000L;
            long sixteenOClock = tenOClock + 6L * 3600L * 1000L;
            long twentyThreeOClock = sixteenOClock + 7L * 3600L * 1000L;
            // 简单粗暴的时间计算方式
            long current = currentTime;

            if (dayOfWeek == 0 || dayOfWeek == 2 || dayOfWeek == 4) {
                if (current < tenOClock) {
                    return new MessageTimeAndType(tenOClock,MessageTimeAndType.TYPE_ASK);
                }
            }

            if (dayOfWeek == 1 || dayOfWeek == 3) {
                if (current < sixteenOClock) {
                    return new MessageTimeAndType(sixteenOClock,MessageTimeAndType.TYPE_KNOWLEDGE);
                }
            }
            if(current < twentyThreeOClock){
                return new MessageTimeAndType(twentyThreeOClock,MessageTimeAndType.TYPE_NIGHT);
            }
            beginOfToday += 24L * 3600L * 1000L;
        }
    }

    static class MessageTimeAndType{
        public long time;
        public int type;

        public MessageTimeAndType(long time, int type) {
            this.time = time;
            this.type = type;
        }

        public static final int TYPE_ASK =1;
        public static final int TYPE_KNOWLEDGE =2;
        public static final int TYPE_NIGHT =3;
    }

}
